package com.crack.nga2.span;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by lenovo on 2016/1/2.
 */
public class SpanUtil {
    public static Drawable listDrawable;
    public static Drawable collapseDrawable;


    public static SpannableStringBuilder getQuote(StringBuilder string) {
        SpannableStringBuilder quote = new SpannableStringBuilder();
        Log.i("tag", "43" + string.toString());
        Pattern p = Pattern.compile("(\\[quote\\])(.*?)(\\[/quote\\])");
        Matcher m = p.matcher(string.toString());
        int offset = 0;
        while (m.find()) {
            int start = m.start(1) - offset;
            int end = m.end(3) - offset;
            Log.i("tag", "50," + start + "," + end);
            //引用内容起始和结束位置
            int s = m.start(2) - offset;
            int e = m.end(2) - offset;
            quote.append(string.subSequence(s, e));
            quote.append("\n");
            string.delete(start, end);
            offset += m.group(0).length();
        }
        return quote;
    }

    public static SpannableStringBuilder getQuote(SpannableStringBuilder sp) {
        SpannableStringBuilder quote = new SpannableStringBuilder();
        Pattern p = Pattern.compile("(\\[quote\\])(.*?)(\\[/quote\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp.toString());
        int offset = 0;
        while (m.find()) {
            int start = m.start(1) - offset;
            int end = m.end(3) - offset;
            //引用内容起始和结束位置
            int s = m.start(2) - offset;
            int e = m.end(2) - offset;
            quote.append(sp.subSequence(s, e));
            quote.append("\n");
            sp.delete(start, end);
            offset += m.group(0).length();
        }
        return quote;
    }

    public static SpannableStringBuilder formatSpan(String string
            , EmotionGetter emotionGetter, PidClick pidClick, UidClick uidClick, UrlClick urlClick) {
        string = string.replaceAll("<br/>", "\n");
        SpannableStringBuilder sp = SpannableStringBuilder.valueOf(string);
        if (string.contains("color")) {
            colorSpan(sp);
        }
        if (string.contains("size")) {
            fontSpan(sp);
        }
        if (string.contains("===")) {
            pSpan(sp);
        }
        if (string.contains("[del]")) {
            simpleSpan(sp, "del");
        }
        if (string.contains("[i]")) {
            simpleSpan(sp, "i");
        }
        if (string.contains("[b]")) {
            simpleSpan(sp, "b");
        }
        if (string.contains("[u]")) {
            simpleSpan(sp, "u");
        }
        if (string.contains("[list]")) {
            listSpan(sp, listDrawable);
        }
//        if (string.contains("[img]")) {
//            imageSpan(sp, asyncImageGetter, textView);
//        }
        if (string.contains("[s:")) {
            emotionSpan(sp, emotionGetter);
        }
        if (string.contains("[pid")) {
            pidSpan(sp, pidClick, collapseDrawable);
        }
        if (string.contains("[uid")) {
            uidSpan(sp, uidClick);
        }
        if (string.contains("[url")) {
            urlSpan(sp, urlClick);
        }
        if (string.contains("[img]")) {
            imageSpan(sp);
        }
        return sp;
    }


    public static void collapseSpan(final SpannableStringBuilder sp, final TextView textView) {
        Pattern p = Pattern.compile("(\\[collapse(=.*)?\\])(.*?)(\\[/collapse\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            int end = m.end() - offset;
            String coll = m.group(2);
            final int s = m.start(3) - offset;
            final int e = m.end(3) - offset;
            final SpannableStringBuilder content = (SpannableStringBuilder) sp.subSequence(s, e);
            if (coll == null) {
                coll = "点击显示隐藏内容";
            } else {
                coll = coll.substring(1);
            }
            final String string = "collapse:" + " " + coll;
            Drawable d = collapseDrawable;
            d.setBounds(0, 0, 40, 40);
            SpannableString coll_sp = SpannableString.valueOf(string);
            coll_sp.setSpan(new ClickableImageSpan(d) {
                @Override
                public void onClick(View view) {
                    int start = sp.getSpanStart(this);
                    int end = start + string.length();
                    sp.replace(start, end, content);
                    textView.setText(sp);
                }
            }, 0, "collapse:".length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            sp.replace(start, end, coll_sp);
            offset += m.group(0).length();
            offset -= coll_sp.length();
        }
    }

    public interface EmotionGetter {
        Drawable getDrawable(String source);
    }

    public static void emotionSpan(SpannableStringBuilder sp, EmotionGetter getter) {
        if (getter == null) {
            return;
        }
        Pattern p = Pattern.compile("\\[s:(ac|pst|dt):(.*?)\\]", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        while (m.find()) {
            int start = m.start();
            int end = m.end();
            String name = converterToSpell(m.group(2));
            String source = m.group(1) + "/" + name;
            sp.setSpan(new ImageSpan(getter.getDrawable(source)), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }

    /**
     * [img]abc.jpg[/img]
     */
    public static void imageSpan(SpannableStringBuilder sp, final AsyncImageGetter getter) {
        if (getter == null) {
            return;
        }
        Pattern p = Pattern.compile("\\[img\\](.*?)\\[/img\\]", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        while (m.find()) {
            int start = m.start();
            int end = m.end();
            final String source = m.group(1);
            Drawable d = getter.getDrawable(source);
            sp.setSpan(new ClickableImageSpan(d) {
                @Override
                public void onClick(View view) {
                    getter.doClick(view, source);
                }
            }, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }

    /**
     * [img]abc.jpg[/img]
     */
    public static void imageSpan(SpannableStringBuilder sp) {
        Pattern p = Pattern.compile("\\[img\\](.*?)\\[/img\\]", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            int end = m.end() - offset;
            String source = m.group(1);
            sp.replace(start, end, "m");
            offset += m.group().length() - 1;
            Drawable d = ImageSpanWrapper.defaultDrawable;
            ClickableImageSpan imageSpan = new ClickableImageSpan(d, source);
            sp.setSpan(imageSpan, start, start + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }

    public interface UrlClick {
        void doClick(String url);
    }

    public static SpannableStringBuilder urlSpan(SpannableStringBuilder sp, UrlClick urlClick) {
        //分两种情况
        //[url]http://....[/url]和[url=http://...]点此链接[/url]
        //第一种
        url1(sp, urlClick);
        //第二种
        url2(sp, urlClick);
        return sp;
    }

    private static void url1(SpannableStringBuilder sp, final UrlClick urlClick) {
        Pattern p = Pattern.compile("(\\[url\\])(.*?)(\\[/url\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            int end = m.end() - offset;
            final String url = m.group(2);
            sp.setSpan(new ClickableSpan() {
                @Override
                public void updateDrawState(TextPaint ds) {
                    ds.setColor(Color.rgb(148, 135, 96));
                    ds.setUnderlineText(true);
                }

                @Override
                public void onClick(View widget) {
                    if (urlClick != null) {
                        urlClick.doClick(url);
                    }
                }
            }, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            //删除开始标签
            sp.delete(m.start(1) - offset, m.start(1) - offset + m.group(1).length());
            offset += m.group(1).length();
            //删除结束标签
            sp.delete(m.start(3) - offset, m.start(3) - offset + m.group(3).length());
            offset += m.group(3).length();
        }
    }

    private static void url2(SpannableStringBuilder sp, final UrlClick urlClick) {
        Pattern p = Pattern.compile("(\\[url=(.*?)\\]).*?(\\[/url\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            int end = m.end() - offset;
            final String url = m.group(2);
            sp.setSpan(new ClickableSpan() {
                @Override
                public void updateDrawState(TextPaint ds) {
                    ds.setColor(Color.rgb(148, 135, 96));
                    ds.setUnderlineText(true);
                }

                @Override
                public void onClick(View widget) {
                    if (urlClick != null) {
                        urlClick.doClick(url);
                    }
                }
            }, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            //删除开始标签
            sp.delete(m.start(1) - offset, m.start(1) - offset + m.group(1).length());
            offset += m.group(1).length();
            //删除结束标签
            sp.delete(m.start(3) - offset, m.start(3) - offset + m.group(3).length());
            offset += m.group(3).length();
        }
    }

    public interface PidClick {
        void doClick(View widget, int pid, int tid, int lou);
    }

    /**
     * 切记在TextView中setTag(int lou);
     */
    private static SpannableStringBuilder pidSpan(SpannableStringBuilder sp, final PidClick pidClick, Drawable clickDrawable) {
        final Pattern p = Pattern.compile("(\\[pid=(.*)\\]).*?(\\[/pid\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        while (m.find()) {
            int start = m.start();
            int end = m.end();
            String string = m.group(2);
            final int pid;
            final int tid;
            if (string.matches("\\d+,\\d+,\\d+")) {
                String[] strings = string.split(",");
                pid = Integer.parseInt(strings[0]);
                tid = Integer.parseInt(strings[1]);
            } else if (string.matches("\\d+")) {
                pid = 0;
                tid = Integer.parseInt(string);
            } else {
                pid = -1;
                tid = -1;
            }
            sp.setSpan(new ClickableImageSpan(clickDrawable) {
                @Override
                public void onClick(View view) {
                    Object object = view.getTag();
                    int lou = -1;
                    if (object instanceof Integer) {
                        lou = (int) object;
                    }
                    Log.i("tag", pid + "," + tid + "," + lou);
                    if (pidClick != null) {
                        if (pid != -1 && tid != -1 && lou != -1) {
                            pidClick.doClick(view, pid, tid, lou);
                        }
                    }
                }
            }, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return sp;
    }

    public interface UidClick {
        void doClick(View widget, int uid);

    }

    private static SpannableStringBuilder uidSpan(SpannableStringBuilder sp, final UidClick uidClick) {
        Pattern p = Pattern.compile("(\\[uid=(\\d+)\\]).*?(\\[/uid\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            int end = m.end() - offset;
            final int uid = Integer.parseInt(m.group(2));
            sp.setSpan(new ClickableSpan() {
                @Override
                public void updateDrawState(TextPaint ds) {
                    ds.setColor(Color.rgb(148, 135, 96));
                    ds.setUnderlineText(true);
                }

                @Override
                public void onClick(View widget) {
                    if (uidClick != null) {
                        uidClick.doClick(widget, uid);
                    }
                }
            }, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            //删除开始标签
            sp.delete(m.start(1) - offset, m.start(1) - offset + m.group(1).length());
            offset += m.group(1).length();
            //删除结束标签
            sp.delete(m.start(3) - offset, m.start(3) - offset + m.group(3).length());
            offset += m.group(3).length();
        }
        return sp;
    }

    /**
     * [color=red]xxxxxx[/color]
     */
    private static SpannableStringBuilder colorSpan(SpannableStringBuilder sp) {
        Pattern p = Pattern.compile("(\\[color=(.*?)\\]).*?(\\[/color\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            int end = m.end() - offset;
            String color = m.group(2);
            sp.setSpan(new ForegroundColorSpan(getColor(color)), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            //删除开始标签
            sp.delete(m.start(1) - offset, m.start(1) - offset + m.group(1).length());
            offset += m.group(1).length();
            //删除结束标签
            sp.delete(m.start(3) - offset, m.start(3) - offset + m.group(3).length());
            offset += m.group(3).length();
        }
        return sp;
    }

    private static SpannableStringBuilder fontSpan(SpannableStringBuilder sp) {
        Pattern p = Pattern.compile("(\\[size=(\\d*?)%\\]).*?(\\[/size\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            int end = m.end() - offset;
            int size = Integer.parseInt(m.group(2));
            float f = size * 1.0f / 100;
            sp.setSpan(new RelativeSizeSpan(f), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            //删除开始标签
            sp.delete(m.start(1) - offset, m.start(1) - offset + m.group(1).length());
            offset += m.group(1).length();
            //删除结束标签
            sp.delete(m.start(3) - offset, m.start(3) - offset + m.group(3).length());
            offset += m.group(3).length();
        }
        return sp;
    }

    /**
     * b,i,u,del标签
     */
    private static SpannableStringBuilder simpleSpan(SpannableStringBuilder sp, String span) {
        Pattern p = Pattern.compile("(\\[" + span + "\\]).*?(\\[/" + span + "\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            int end = m.end() - offset;
            sp.setSpan(getSimpleSpan(span), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            //删除开始标签
            sp.delete(m.start(1) - offset, m.start(1) - offset + m.group(1).length());
            offset += m.group(1).length();
            //删除结束标签
            sp.delete(m.start(2) - offset, m.start(2) - offset + m.group(2).length());
            offset += m.group(2).length();
        }
        return sp;
    }

    private static SpannableStringBuilder listSpan(SpannableStringBuilder sp, Drawable d) {
        Pattern p = Pattern.compile("(\\[list\\])(.*?)(\\[/list\\])", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            // 删除开始标签
            sp.delete(m.start(1) - offset, m.start(1) - offset + m.group(1).length());
            offset += m.group(1).length();
            Pattern pp = Pattern.compile("\\[\\*\\]");
            Matcher mm = pp.matcher(m.group(2));
            int index = 0;
            while (mm.find()) {
                int s = mm.start() + start + index;
                sp.insert(s, "\n");
                index++;
                s++;
                offset--;
                sp.setSpan(new VerticalImageSpan(d), s, s + 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }

            // 删除结束标签
            sp.delete(m.start(3) - offset, m.start(3) - offset + m.group(3).length());
            offset += m.group(3).length();
            int end = m.end() - offset;
            sp.insert(end, "\n");
            offset--;
        }
        return sp;
    }

    private static SpannableStringBuilder pSpan(SpannableStringBuilder sp) {
        Pattern p = Pattern.compile("(===).*?(===)", Pattern.DOTALL);
        Matcher m = p.matcher(sp);
        int offset = 0;
        while (m.find()) {
            int start = m.start() - offset;
            sp.insert(start, "\n");
            offset--;
            start = m.start() - offset;
            int end = m.end() - offset;
            sp.insert(end, "\n");
            sp.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            // 删除开始标签
            sp.delete(m.start(1) - offset, m.start(1) - offset + m.group(1).length());
            offset += m.group(1).length();
            // 删除结束标签
            sp.delete(m.start(2) - offset, m.start(2) - offset + m.group(2).length());
            offset += m.group(2).length();
            // sp.insert(end - offset, "\n");
            offset--;
        }
        return sp;
    }

    private static Object getSimpleSpan(String span) {
        switch (span) {
            case "b":
                return new StyleSpan(Typeface.BOLD);
            case "i":
                return new StyleSpan(Typeface.ITALIC);
            case "u":
                return new UnderlineSpan();
            case "del":
                return new StrikethroughSpan();

        }
        return new StyleSpan(Typeface.NORMAL);
    }

    private static int getColor(String color) {
        color = color.toLowerCase();
        switch (color) {
            case "red":
                return Color.RED;
            case "crimson":
                return Color.rgb(220, 20, 60);
            case "firebrick":
                return Color.rgb(178, 34, 34);
            case "darkred":
                return Color.rgb(139, 0, 0);
            case "green":
                return Color.GREEN;
            case "limegreen":
                return Color.rgb(50, 205, 50);
            case "seagreen":
                return Color.rgb(46, 139, 87);
            case "teal":
                return Color.rgb(0, 128, 128);
            case "deeppink":
                return Color.rgb(255, 20, 147);
            case "tomato":
                return Color.rgb(255, 99, 71);
            case "coral":
                return Color.rgb(255, 127, 80);
            case "purple":
                return Color.rgb(128, 0, 128);
            case "indigo":
                return Color.rgb(75, 0, 130);
            case "skyblue":
                return Color.rgb(135, 206, 235);
            case "royalblue":
                return Color.rgb(65, 105, 225);
            case "blue":
                return Color.BLUE;
            case "darkblue":
                return Color.rgb(0, 0, 139);
            case "orange":
                return Color.rgb(255, 165, 0);
            case "orangered":
                return Color.rgb(255, 69, 0);
            case "burlywood":
                return Color.rgb(222, 184, 135);
            case "sandybrown":
                return Color.rgb(244, 164, 96);
            case "sienna":
                return Color.rgb(160, 82, 45);
            case "chocolate":
                return Color.rgb(210, 105, 30);
            case "silver":
                return Color.rgb(192, 192, 192);

        }
        return Color.BLACK;
    }

    public interface AsyncImageGetter {
        Drawable getDrawable(String source);

        void doClick(View view, String source);
    }

    /**
     * 汉字转换位汉语拼音，英文字符不变
     *
     * @param chines 汉字
     * @return 拼音
     */
    private static String converterToSpell(String chines) {
        String pinyinName = "";
        char[] nameChar = chines.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (int i = 0; i < nameChar.length; i++) {
            if (nameChar[i] > 128) {
                try {
                    pinyinName += PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat)[0];
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                }
            } else {
                pinyinName += nameChar[i];
            }
        }
        return pinyinName;
    }
}
